#region Imported NameSpaces
using System;
using System.Collections;
using System.Data;
using SqlClient=System.Data.SqlClient;

using BO = PHSRAG.Insight21.BusinessObjects;
using Utility = PHSRAG.Utility;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using DataAccess = PHSRAG.Utility.DataAccess;
#endregion

namespace PHSRAG.Insight21.Humans
{
	/// <summary>
	/// Represents a drug that is involved in the study
	/// Additional feature:
	///		-->Raises the request to the listAdditionRequests object for adding a new drug to the legacy database.
	/// </summary>
	public class Drug:BO.SmartBusinessObject
	{		
		#region private instance variables
		private string itemName;
		private string marketingName;
		private string genericName;
		private string type;
		private string manufacturer;
		private string biologicClass;
		#endregion

		#region private constants
		private const string ColumnDrugId = "nItemCode";
		private const string ColumnDrugItemName = "sItemName";
		private const string ColumnDrugInvestigationalName = "InvestigaionalName";
		private const string ColumnDrugMarketingName = "sPreGenericName";
		private const string ColumnDrugGenericName = "sGenericName";
		private const string ColumnDrugType = "sItemType";
		private const string ColumnDrugManufacturer = "sManufacturer";
		private const string ColumnDrugBiologicClass = "sDrugBiologicClass";
		#endregion

		#region private constant cacheKey
		private const string DrugKey = "DrugKey_D128E1F5-47C7-4b47-B643-FDC961A8ED05";
		#endregion
	
		#region public properties
		/// <summary>Gets/Sets Investigational(Item Name) of the Drug </summary>
		public string InvestigationalName
		{
			get{return itemName;}
			set { SetDirty( ref itemName,value);}
		}
		/// <summary>Gets/Sets the marketing name (Pre-Generic) name of the drug </summary>
		public string MarketingName
		{
			get{return marketingName;}
			set{ SetDirty( ref marketingName,value);}
		}
		/// <summary>Gets/Sets the generic name of the drug </summary>
		public string GenericName
		{
			get{return genericName;}
			set{ SetDirty( ref genericName,value);}
		}
		/// <summary>Gets/Sets the type of the drug </summary>
		public string Type
		{
			get{return type;}
			set{ SetDirty(ref type,value);}
		}
		/// <summary>Gets/Sets the manufacturer name of the drug </summary>
		public string Manufacturer
		{
			get{return manufacturer;}
			set{ SetDirty( ref manufacturer,value);}
		}
		/// <summary>Gets/Sets the Biologic Class of the drug (Not available from the UI)</summary>
		public string BiologicClass
		{
			get{return biologicClass;}
			set { SetDirty( ref biologicClass,value);}
		}
		/// <summary>
		/// Cache Key uniquely identifies this object within the cache.
		/// </summary>
		/// <returns>Unique string(Key)for this object.</returns>
		public override string CacheKey()
		{
			return DrugKey;
		}
		#endregion
		
		#region Drugs constructor
		/// <summary>
		/// Constructs a new drug object based on the Cache Policy  and the datarow passed in as a parameter. 
		/// All the data members of the current object will be set to the values from the datarow.
		/// </summary>
		/// <param name="cachePolicy">Prevalent cache Policy</param>
		/// <param name="row">The datarow passsed in as parameter</param>
		public Drug(ICachePolicy cachePolicy, DataRow row) : base(cachePolicy)
		{	
			PopulateDataMembers(row, (int)row[ColumnDrugId]);
		}

		/// <summary>
		/// Constructs a new drug object based on the Cache Policy passed in as a parameter. 
		/// </summary>
		/// <param name="cachePolicy">available cahche policy</param>
		public Drug(ICachePolicy cachePolicy) : base(cachePolicy)
		{
			
		}
		#endregion

		#region caching
		/// <summary>
		/// Cache the current object using the prevalent cache policy.
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(DrugKey, this);
		}

		/// <summary>
		/// Remove an object from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(DrugKey);
		}
		#endregion

		#region public Methods
		/// <summary>
		/// Adds the drug to the Legacy database and adds a addition request for the drug to the Insight database
		/// </summary>
		/// <param name="conn">Insight Connection string</param>
		/// <param name="rexConnection">Legacy database connection string</param>
		/// <param name="protocolProcessId">Protocol process Id to which the drug is added</param>
		/// <returns>The id of the new drug inserted</returns>
		public int AddRequest(string conn,string rexConnection,int protocolProcessId)
		{ 
			SqlClient.SqlConnection connection = new SqlClient.SqlConnection(rexConnection);
			SqlClient.SqlTransaction transaction = null;
			try
			{   
				connection.Open();
				transaction = connection.BeginTransaction( System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
				Save(transaction);
				//Addition request to the Insight database
				ListAdditionRequest newDrug = new ListAdditionRequest(CachePolicy, type, Id.ToString(), itemName, protocolProcessId);
				newDrug.Save(conn);
				transaction.Commit();
				return newDrug.Id;
		
			}
			catch(Exception ex)
			{
				if( transaction != null )
					transaction.Rollback();
				throw new Exception("Failed to add drug request. Error occurred while trying to execute the AddRequest() of the Drug object", ex);
			}
			finally
			{
				if (connection.State != ConnectionState.Closed)
					connection.Close();
			}
		}
		#endregion

		#region protected override methods
		/// <summary>Override method for save (Saves the drug item) </summary>
		/// <param name="sqlTransaction">Transaction object  </param>
		protected override void SaveObject(System.Data.SqlClient.SqlTransaction sqlTransaction)
		{
			try
			{
				Id=Convert.ToInt32(DataAccess.ExecuteScalar(sqlTransaction.Connection,sqlTransaction, "spDrugMaintUpdate", 
					DataAccess.BuildSqlParameterArray("@nItemCode", SqlDbType.Int, Id,
					"@sItemName",SqlDbType.VarChar,itemName,
					"@sGenericName",SqlDbType.VarChar,genericName,
					"@sPreGenericName",SqlDbType.VarChar,marketingName,
					"@sDrugBiologicClass",SqlDbType.VarChar,biologicClass,
					"@sManufacturer",SqlDbType.VarChar,manufacturer,
					"@sItemType",SqlDbType.VarChar,type,
					"@bSchedule2",SqlDbType.Bit,false,//no value available for this parameter from the GUI
					"@sNote",SqlDbType.VarChar,DBNull.Value//no value available for this parameter from the GUI
					)));
			}
			catch(Exception ex)
			{
				throw new Exception("Failed to save drug. Error occurred while trying to execute the SaveObject() of the Drug object", ex);
			}
		}
		
		
		/// <summary>
		/// Delete Drug. This method is not currently implemented.
		/// Calling this method will currently throw an exception.
		/// </summary>
		/// <param name="sqlTransaction">DB Transaction to use during deletion.</param>
		protected override void DeleteObject(System.Data.SqlClient.SqlTransaction sqlTransaction)
		{
			throw new Exception("Deletion of a drug is not supported.");
		}

		
		/// <summary>Loads the drug object based on the specified item code</summary>
		/// <param name="rexConnection">Legacy database connection string</param>
		/// <param name="args">ItemCode of the drug to be loaded</param>
		public override void Load(string rexConnection, params object[] args)
		{
			try
			{
				if (args.Length != 1)
				{
					throw new Exception("Drug.Load() requires only itemCode as parameter");
				}
				else 
				{
					DataTable dataTable = DataAccess.GetDataTable(rexConnection, "spDrugMaintGet",
						DataAccess.BuildSqlParameterArray("@nItemCode", SqlDbType.Int, (int)args[0]));
					if((dataTable!=null) && (dataTable.Rows.Count!=0))
					{
						PopulateDataMembers(dataTable.Rows[0], (int)args[0] );
					}
					else
					{
						throw new Exception("Failed to load the drug. The stored procedure returned incorrect results.");
					}
				}						
			}
			catch(Exception ex)
			{
				throw new Exception("Failed to load drug.", ex);
			}
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Converts a database column value to a string
		/// </summary>
		/// <param name="columnValue">Value from the database</param>
		/// <returns>An equivalent string</returns>
		private string GetColumnValue(object columnValue)
		{
			return (columnValue == DBNull.Value) ? string.Empty : columnValue.ToString();
		}


		/// <summary>
		/// Sets the drug item to respective datarow items 
		/// This method is called from the constructor and load(),but the datarow passed from the load method does not have the drug itemCode.
		/// Hence the drug itemcode is passed in as the second parameter from both the methods.
		/// </summary>
		/// <param name="drugRow">Drug item values for a drug</param>
		/// <param name="itemCode">Drug Itemcode</param>
		private void PopulateDataMembers(DataRow drugRow,int itemCode)
		{
			try
			{
				Id = itemCode;
				itemName = GetColumnValue(drugRow[ColumnDrugItemName]);
				marketingName = GetColumnValue(drugRow[ColumnDrugMarketingName]);
				genericName = GetColumnValue(drugRow[ColumnDrugGenericName]);
				type = GetColumnValue(drugRow[ColumnDrugType]);
				manufacturer = GetColumnValue(drugRow[ColumnDrugManufacturer]);
				biologicClass = GetColumnValue(drugRow[ColumnDrugBiologicClass]);
			}
			catch(Exception ex)
			{
				throw new Exception("Failed to populate drug data members.", ex);
			}
		}

		#endregion
		
	}
	
}
